using Circus.CodeEditor;
using Circus.Syntax;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
namespace Circus.CodeEditor.TextSource
{
	public class TextStrings : IStringList
	{
		private TextSource source;
		private CodeEditor owner;
		private string lineTerminator = "\r\n";
        private List<StringItem> list;
		private StringBuilder tabBuilder;
		private int[] tabStops = new int[]
		{
			EditConsts.DefaultTabStop
		};
		private List<int> tabList;
		private bool useSpaces;
		private char[] tabArray = new char[]
		{
			'\t'
		};
		private Hashtable delimTable;
		private char[] delimiters = EditConsts.DefaultDelimiters.ToCharArray();
		private int updateCount;
		private int firstChanged = -1;
		private int lastChanged = -1;
	    private event EventHandler notifyHandler;
		[Description("Gets or sets the strings in the \"ITextStrings\" as a single string with the individual strings delimited by carriage returns.")]
		public virtual string Text
		{
			get
			{
				StringBuilder stringBuilder = new StringBuilder();
				foreach (StringItem current in this.list)
				{
					stringBuilder.Append(current.String + this.lineTerminator);
				}
				if (stringBuilder.Length >= 2)
				{
					stringBuilder.Remove(stringBuilder.Length - this.lineTerminator.Length, this.lineTerminator.Length);
				}
				return stringBuilder.ToString();
			}
			set
			{
				this.SetTextAndData(value, null);
			}
		}
		
		[Description("Represents number of the first changed line.")]
		public virtual int FirstChanged
		{
			get
			{
				return this.firstChanged;
			}
		}
		[Description("Represents number of the last changed line.")]
		public virtual int LastChanged
		{
			get
			{
				return this.lastChanged;
			}
		}
		
	
		public virtual string this[int index]
		{
			get
			{
				return (index >= 0 && index < this.Count) ? this.list[index].String : string.Empty;
			}
			set
			{
				if (index >= 0 && index < this.list.Count)
				{
					StringItem stringItem = this.list[index];
					stringItem.String = value;
					StringItem expr_34 = stringItem;
					expr_34.State &= ~ItemState.Parsed;
					this.Changed(index);
				}
			}
		}
		[Description("Represents number of strings in the collection.")]
		public virtual int Count
		{
			get
			{
				return this.list.Count;
			}
		}
		[Description("Gets a value indicating whether the collection is read-only.")]
		public virtual bool IsReadOnly
		{
			get
			{
				return false;
			}
		}
		[DefaultValue("\r\n"), Description("Gets or sets a string value that terminates line.")]
		public virtual string LineTerminator
		{
			get
			{
				return this.lineTerminator;
			}
			set
			{
				if (this.lineTerminator != value)
				{
					this.lineTerminator = value;
					this.OnLineTerminatorChanged();
				}
			}
		}
		[Description("Gets or sets the character columns that the cursor will move to each time you press Tab.")]
		public virtual int[] TabStops
		{
			get
			{
				return this.tabStops;
			}
			set
			{
				this.tabStops = new int[value.Length];
				Array.Copy(value, this.tabStops, value.Length);
				this.tabList.Clear();
				int num = 0;
				int[] array = this.tabStops;
				for (int i = 0; i < array.Length; i++)
				{
					int num2 = array[i];
					if (num2 <= num)
					{
						ErrorHandler.Error(new Exception(string.Format(StringConsts.InvalidTabStop, value.ToString())));
					}
					num = num2;
				}
			}
		}
		[Description("Gets or sets a value indicating whether indent or TAB operations insert space characters rather than TAB characters.")]
		public virtual bool UseSpaces
		{
			get
			{
				return this.useSpaces;
			}
			set
			{
				if (this.useSpaces != value)
				{
					this.useSpaces = value;
					this.OnUseSpacesChanged();
				}
			}
		}
		public virtual Hashtable DelimTable
		{
			get
			{
				return this.delimTable;
			}
		}
		[Description("Gets or sets an array of characters used as delimiters between words in the text.")]
		public virtual char[] Delimiters
		{
			get
			{
				return this.delimiters;
			}
			set
			{
				if (this.delimiters != value)
				{
					this.delimiters = value;
					this.OnDelimitersChanged();
				}
			}
		}
		[Description("Gets or sets \"Delimiters\" as a single string.")]
		public virtual string DelimiterString
		{
			get
			{
				return new string(this.Delimiters);
			}
			set
			{
				this.Delimiters = value.ToCharArray();
			}
		}
		
		public virtual CodeEditor Owner
		{
			get
			{
				return this.owner;
			}
			set
			{
				if (this.owner != value)
				{
					this.owner = value;
					this.OnOwnerChanged();
				}
			}
		}
		public TextStrings(TextSource source) : this()
		{
			this.source = source;
		}
		public TextStrings()
		{
			this.list = new List<StringItem>();
			this.tabList = new List<int>();
			this.tabBuilder = new StringBuilder();
			this.delimTable = new Hashtable();
			this.UpdateDelimTable();
		}
		~TextStrings()
		{
			this.delimTable.Clear();
		}
		public virtual StringItem CreateStringItem(string s)
		{
			StringItem result;
			if (this.source != null)
			{
				result = this.source.CreateStringItem(s);
			}
			else
			{
				result = new StringItem(s);
			}
			return result;
		}
		private StringItemInfo[] GetColorData(string s, int left, int len)
		{
			StringItemInfo[] result;
			if (left < s.Length)
			{
				if (left + len < s.Length)
				{
					s = s.Substring(left, len);
				}
				else
				{
					s = s.Substring(left);
				}
				StringItemInfo[] array = new StringItemInfo[s.Length];
				for (int i = 0; i < s.Length; i++)
				{
					array[i].Data = (byte)s[i];
				}
				result = array;
			}
			else
			{
				result = null;
			}
			return result;
		}
		protected virtual int AddData(string value, StringItemInfo[] colorData)
		{
			StringItem stringItem = this.CreateStringItem(value);
			if (colorData != null && colorData.Length == value.Length)
			{
				stringItem.TextData = colorData;
			}
			this.list.Add(stringItem);
			int num = this.list.Count - 1;
			this.Changed(num);
			return num;
		}

	    protected static bool IsDelimiter(string s, int pos, Hashtable delimTable)
		{
			char c = s[pos];
			return c <= ' ' || delimTable.ContainsKey(c);
		}
		protected static bool IsWholeWord(Hashtable delimTable, string s, int start, int len, ref int wordStart, ref int wordEnd)
		{
			wordStart = start;
			wordEnd = start + len;
			int length = s.Length;
			if (wordStart <= 0 || !TextStrings.IsDelimiter(s, wordStart, delimTable))
			{
				while (wordStart > 0 && !TextStrings.IsDelimiter(s, wordStart - 1, delimTable))
				{
					wordStart--;
				}
			}
			if (wordEnd >= length - 1 || wordEnd <= 0 || !TextStrings.IsDelimiter(s, wordEnd - 1, delimTable))
			{
				while (wordEnd < length && !TextStrings.IsDelimiter(s, wordEnd, delimTable))
				{
					wordEnd++;
				}
			}
			return wordStart == start && len == wordEnd - wordStart;
		}
		public static bool IsWhitespace(char ch)
		{
			return ch == ' ' || ch == '\t' || ch == '\u3000';
		}
		public static int TextPointToAbsolutePosition(IList<string> list, Point position, string lineTerminator)
		{
			int num = 0;
			int length = lineTerminator.Length;
			int count = list.Count;
			for (int i = 0; i < position.Y; i++)
			{
				num += ((i < count) ? list[i].Length : 0) + length;
			}
			if (position.Y < count)
			{
				num += Math.Min(position.X, list[position.Y].Length);
			}
			return num;
		}
		public static Point AbsolutePositionToTextPoint(IList<string> list, int position, string lineTerminator)
		{
			Point result = new Point(0, 0);
			int length = lineTerminator.Length;
			int count = list.Count;
			while (position > 0)
			{
				int num = (result.Y < count) ? list[result.Y].Length : 0;
				if (position <= num)
				{
					result.X = position;
					break;
				}
				result.Y++;
				position -= num + length;
			}
			return result;
		}
		public static bool Find(IStringList list, Hashtable delimTable, string s, SearchOptions options, Regex expression, ref Point position, out int len, out Match match, string lineTerminator)
		{
			match = null;
			len = ((s != null) ? s.Length : 0);
			bool result;
			if (s == null || s == string.Empty)
			{
				result = false;
			}
			else
			{
				bool flag = (options & SearchOptions.CaseSensitive) == SearchOptions.None && expression == null;
				if (flag)
				{
					s = s.ToUpper();
				}
				int num = 0;
				int num2 = 0;
				if ((options & SearchOptions.BackwardSearch) != SearchOptions.None)
				{
					if (expression != null && (expression.Options & RegexOptions.Multiline) != RegexOptions.None)
					{
						int num3 = TextStrings.TextPointToAbsolutePosition(list, position, lineTerminator);
						string text = list.Text;
						match = expression.Match(text, Math.Min(num3, text.Length));
						if (match.Success && match.Length > 0)
						{
							len = match.Length;
							position = TextStrings.AbsolutePositionToTextPoint(list, match.Index, lineTerminator);
							result = true;
							return result;
						}
						result = false;
						return result;
					}
					else
					{
						position.Y = Math.Min(position.Y, list.Count - 1);
						while (position.Y >= 0)
						{
							string text2 = list[position.Y];
							if (position.X > 0 || (text2 == string.Empty && position.X == 0 && expression != null))
							{
								if (flag)
								{
									text2 = text2.ToUpper();
								}
								if (expression != null)
								{
									match = ((text2 == string.Empty) ? expression.Match(text2) : expression.Match(text2, Math.Min(position.X, text2.Length)));
									if (match.Success)
									{
										len = match.Length;
										position.X = match.Index;
									}
									else
									{
										position.X = -1;
									}
								}
								else
								{
									if (text2 != string.Empty)
									{
										position.X = text2.LastIndexOf(s, Math.Min(position.X - 1, text2.Length - 1));
									}
									else
									{
										position.X = -1;
									}
								}
								if (position.X >= 0 && (options & SearchOptions.WholeWordsOnly) != SearchOptions.None && !TextStrings.IsWholeWord(delimTable, text2, position.X, len, ref num, ref num2))
								{
									position.X = num - 1;
									continue;
								}
								if (position.X >= 0)
								{
									result = true;
									return result;
								}
							}
							position.Y--;
							if (position.Y >= 0)
							{
								position.X = list[position.Y].Length;
							}
						}
					}
				}
				else
				{
					if (expression != null && (expression.Options & RegexOptions.Multiline) != RegexOptions.None)
					{
						int num3 = TextStrings.TextPointToAbsolutePosition(list, position, lineTerminator);
						string text = list.Text;
						if (num3 < text.Length)
						{
							match = expression.Match(text, num3);
							if (match.Success && match.Length > 0)
							{
								len = match.Length;
								position = TextStrings.AbsolutePositionToTextPoint(list, match.Index, lineTerminator);
								result = true;
								return result;
							}
						}
						result = false;
						return result;
					}
					while (position.Y < list.Count)
					{
						string text2 = list[position.Y];
						if (position.X < text2.Length || (text2 == string.Empty && position.X == 0 && expression != null))
						{
							if (flag)
							{
								text2 = text2.ToUpper();
							}
							position.X = Math.Min(position.X, text2.Length - 1);
							if (expression != null)
							{
								match = ((text2 == string.Empty) ? expression.Match(text2) : expression.Match(text2, position.X));
								if (match.Success)
								{
									len = match.Length;
									position.X = match.Index;
								}
								else
								{
									position.X = -1;
								}
							}
							else
							{
								if (text2 != string.Empty)
								{
									position.X = text2.IndexOf(s, position.X);
								}
								else
								{
									position.X = -1;
								}
							}
							if (position.X >= 0 && (options & SearchOptions.WholeWordsOnly) != SearchOptions.None && !TextStrings.IsWholeWord(delimTable, text2, position.X, len, ref num, ref num2))
							{
								position.X = ((position.X == num2) ? (position.X + 1) : num2);
								continue;
							}
							if (position.X >= 0)
							{
								result = true;
								return result;
							}
						}
						position.Y++;
						position.X = 0;
					}
				}
				result = false;
			}
			return result;
		}
		public virtual StringItem GetItem(int index)
		{
			return (index >= 0 && index < this.Count) ? this.list[index] : this.CreateStringItem(string.Empty);
		}
		public virtual int GetLength(int index)
		{
			return (index >= 0 && index < this.Count) ? this.list[index].String.Length : 0;
		}
		public virtual void SetTextAndData(string text, string data)
		{
			if (this.source != null)
			{
				this.source.BeginUpdate(UpdateReason.Other);
			}
			this.BeginUpdate();
			try
			{
				this.Clear();
				if (text != null && text != string.Empty)
				{
					StringReader stringReader = new StringReader(text);
					int num = 0;
					string text2;
					while ((text2 = stringReader.ReadLine()) != null)
					{
						if (data != null)
						{
							string text3 = text2;
							this.AddData(text3, this.GetColorData(data, num, text3.Length));
							num += text2.Length;
							if (num < text.Length - 1 && text[num] == '\r' && text[num + 1] == '\n')
							{
								num += 2;
							}
							else
							{
								if (num < text.Length && (text[num] == '\r' || text[num] == '\n'))
								{
									num++;
								}
							}
						}
						else
						{
							this.Add(text2);
						}
					}
					char c = text[text.Length - 1];
					if (c == '\r' || c == '\n')
					{
						this.Add(string.Empty);
					}
				}
				if (this.source != null)
				{
					this.source.MoveTo(0, 0);
					this.source.State = (this.source.State | NotifyState.CountChanged);
					if (data != null)
					{
						this.source.SetLastParsed(this.Count);
					}
				}
				this.Changed(0, int.MaxValue);
			}
			finally
			{
				this.EndUpdate();
				if (this.source != null)
				{
					this.source.EndUpdate();
				}
			}
		}
		public virtual void Changed(int index)
		{
			this.Changed(index, index);
		}
		public virtual void Changed(int first, int last)
		{
			if (this.firstChanged == -1)
			{
				this.firstChanged = first;
			}
			else
			{
				this.firstChanged = Math.Min(this.firstChanged, first);
			}
			this.lastChanged = Math.Max(this.lastChanged, last);
			this.Update();
		}
		public virtual char GetCharAt(int x, int y)
		{
			StringItem item = this.GetItem(y);
			char result;
			if (item != null && x >= 0 && x < item.String.Length)
			{
				result = item.String[x];
			}
			else
			{
				result = '\0';
			}
			return result;
		}
		public virtual char GetCharAt(Point position)
		{
			return this.GetCharAt(position.X, position.Y);
		}
		public virtual StringItemInfo GetLexStyle(Point position)
		{
			StringItemInfo[] textData = this.list[position.Y].TextData;
			StringItemInfo stringItemInfo = default(StringItemInfo);
			stringItemInfo.Data = 255;
			return (textData != null && position.X >= 0 && position.X < textData.Length) ? textData[position.X - 1] : stringItemInfo;
		}
		public virtual void AfterSave()
		{
			if (this.source != null)
			{
				this.source.Modified = false;
			}
		}
		public virtual int TextPointToAbsolutePosition(Point position)
		{
			return TextStrings.TextPointToAbsolutePosition(this, position, this.lineTerminator);
		}
		public virtual Point AbsolutePositionToTextPoint(int position)
		{
			return TextStrings.AbsolutePositionToTextPoint(this, position, this.lineTerminator);
		}
	
		public virtual int IndexOf(string item)
		{
			int result;
			for (int i = 0; i < this.Count; i++)
			{
				if (this.list[i].String == item)
				{
					result = i;
					return result;
				}
			}
			result = -1;
			return result;
		}
		public virtual void Insert(int index, string item)
		{
			this.list.Insert(index, this.CreateStringItem(item));
			this.Changed(index, int.MaxValue);
		}
		public virtual void RemoveAt(int index)
		{
			if (index >= 0 && index < this.Count)
			{
				this.list.RemoveAt(index);
				if (index < this.Count)
				{
					StringItem stringItem = this.list[index];
					StringItem expr_45 = stringItem;
					expr_45.State &= ~ItemState.Parsed;
				}
				this.Changed(index, int.MaxValue);
			}
		}
		public virtual void Add(string item)
		{
			this.list.Add(this.CreateStringItem(item));
			int index = this.list.Count - 1;
			this.Changed(index);
		}
		public virtual void Clear()
		{
			this.list.Clear();
			this.Changed(0, int.MaxValue);
		}
		public virtual bool Contains(string item)
		{
			bool result;
			foreach (StringItem current in this.list)
			{
				if (current.String == item)
				{
					result = true;
					return result;
				}
			}
			result = false;
			return result;
		}
		public virtual void CopyTo(string[] array, int arrayIndex)
		{
			for (int i = arrayIndex; i < Math.Min(this.Count + arrayIndex, array.Length); i++)
			{
				array[i] = this[i - arrayIndex];
			}
		}
		public virtual bool Remove(string item)
		{
			int num = this.IndexOf(item);
			bool result;
			if (num >= 0)
			{
				this.RemoveAt(num);
				result = true;
			}
			else
			{
				result = false;
			}
			return result;
		}
		public virtual IEnumerator<string> GetEnumerator()
		{
            return this.list.ConvertAll<string>(new Converter<StringItem, string>(this.StringItemToString)).GetEnumerator();
		}
		protected string StringItemToString(StringItem item)
		{
			return item.String;
		}
		IEnumerator IEnumerable.GetEnumerator()
		{
			return this.list.GetEnumerator();
		}
		public virtual bool Find(string s, SearchOptions options, Regex expression, ref Point position, out int len, out Match match)
		{
			return TextStrings.Find(this, this.delimTable, s, options, expression, ref position, out len, out match, this.lineTerminator);
		}
		protected virtual void OnLineTerminatorChanged()
		{
		}
	
		private int GetStop(int pos)
		{
			int num = this.tabStops.Length;
			int result;
			if (num == 0)
			{
				result = EditConsts.DefaultTabStop;
			}
			else
			{
				int num2 = pos - this.tabStops[num - 1];
				if (num2 >= 0)
				{
					int num3;
					if (num == 1)
					{
						num3 = this.tabStops[0];
					}
					else
					{
						num3 = this.tabStops[num - 1] - this.tabStops[num - 2];
					}
					result = this.tabStops[num - 1] + (num2 / num3 + 1) * num3;
				}
				else
				{
					int num3 = 0;
					while (pos >= this.tabStops[num3])
					{
						num3++;
					}
					result = this.tabStops[num3];
				}
			}
			return result;
		}
		protected virtual void OnUseSpacesChanged()
		{
		}
		public virtual void GetTabString(ref string str, ref StringItemInfo[] data, bool needData, TextUndoList operations)
		{
			if (str != null && !(str == string.Empty) && str.IndexOf('\t') >= 0)
			{
				if (operations == null)
				{
					this.tabBuilder.Length = 0;
				}
				int num = 0;
				int num2 = 0;
				int num3 = 0;
				int num4;
				do
				{
					num4 = str.IndexOf('\t', num3);
					string text = (num4 >= 0) ? str.Substring(num3, num4 - num3) : str.Substring(num3);
					if (num3 == 0)
					{
						if (operations == null)
						{
							this.tabBuilder.Append(text);
						}
						num = text.Length;
						num2 = num;
					}
					else
					{
						int num5 = this.GetTabStop(num) - num;
						if (operations != null)
						{
							operations.Add(new TextUndo(num2, 1, new string(' ', num5)));
						}
						else
						{
							this.tabBuilder.Append(new string(' ', num5));
							this.tabBuilder.Append(text);
						}
						num2 += text.Length + 1;
						num += text.Length + num5;
					}
					if (num4 >= 0)
					{
						num3 = num4 + 1;
					}
				}
				while (num4 >= 0);
				string text2 = (operations == null) ? this.tabBuilder.ToString() : str;
				if (needData)
				{
					StringItemInfo[] array = new StringItemInfo[text2.Length];
					num = 0;
					int num6 = 0;
					num3 = 0;
					do
					{
						num4 = str.IndexOf('\t', num3);
						int num7 = (num4 >= 0) ? (num4 - num3) : (str.Length - num3);
						if (num3 == 0)
						{
							num = num7;
							num6 = num;
							if (num != 0)
							{
								Array.Copy(data, 0, array, 0, num);
							}
						}
						else
						{
							int num5 = this.GetTabStop(num) - num;
							for (int i = num; i < num + num5; i++)
							{
								array[i] = data[num6];
							}
							StringItem.SetTextStyle(ref array, num + num5 / 2, 1, TextStyle.Tabulation);
							Array.Copy(data, num6 + 1, array, num + num5, num7);
							num += num7 + num5;
							num6 += num7 + 1;
						}
						if (num4 >= 0)
						{
							num3 = num4 + 1;
						}
					}
					while (num4 >= 0);
					data = array;
				}
				str = text2;
			}
		}
	
		public virtual string GetTabString(string s)
		{
			StringItemInfo[] array = null;
			this.GetTabString(ref s, ref array, false, null);
			return s;
		}
		public virtual void GetTabString(string s, TextUndoList operations)
		{
			StringItemInfo[] array = null;
			this.GetTabString(ref s, ref array, false, operations);
		}
		public virtual int GetTabStop(int pos)
		{
			int result;
			if (pos == int.MaxValue)
			{
				result = pos;
			}
			else
			{
				for (int i = this.tabList.Count; i <= pos; i++)
				{
					this.tabList.Add(this.GetStop(i));
				}
				result = this.tabList[pos];
			}
			return result;
		}
	
		public virtual string GetIndentString(int count, int pos)
		{
			return this.GetIndentString(count, pos, this.useSpaces);
		}
		public virtual string GetIndentString(int count, int p, bool useSpaces)
		{
			string result;
			if (useSpaces)
			{
				result = new string(' ', count);
			}
			else
			{
				int i = 0;
				int num = 0;
				while (i < count)
				{
					int num2 = this.GetTabStop(p) - p;
					if (i + num2 > count)
					{
						break;
					}
					i += num2;
					p += num2;
					num++;
				}
				result = new string('\t', num) + new string(' ', count - i);
			}
			return result;
		}
		public virtual int TabPosToPos(string s, int pos)
		{
			int result;
			if (pos < 0)
			{
				result = pos;
			}
			else
			{
				int num = pos - s.Length;
				pos = this.GetTabString(s.Substring(0, Math.Min(pos, s.Length))).Length;
				if (num > 0)
				{
					result = pos + num;
				}
				else
				{
					result = pos;
				}
			}
			return result;
		}
		public virtual int PosToTabPos(string s, int pos)
		{
			return this.PosToTabPos(s, pos, false);
		}
		public virtual int PosToTabPosOriginal(string s, int pos, bool tabEnd)
		{
			int num = 0;
			int num2 = 0;
			string[] array = s.Split(this.tabArray);
			for (int i = 0; i < array.Length - 1; i++)
			{
				int length = array[i].Length;
				int num3 = this.GetTabStop(num + length) - num - length;
				num += length + num3;
				if (pos < num)
				{
					if (num - pos < num3 && !tabEnd)
					{
						num2 += num3 - (num - pos);
					}
					break;
				}
				num2 += num3 - 1;
			}
			return pos - num2;
		}
		public virtual int PosToTabPos(string s, int pos, bool tabEnd)
		{
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int length = s.Length;
			int num4;
			int num6;
			do
			{
				num4 = s.IndexOf('\t', num3);
				if (num4 < 0)
				{
					break;
				}
				int num5 = num4 - num3;
				num6 = this.GetTabStop(num + num5) - num - num5;
				num += num5 + num6;
				if (pos < num)
				{
					goto Block_2;
				}
				num2 += num6 - 1;
				if (num4 >= 0)
				{
					num3 = num4 + 1;
				}
			}
			while (num4 >= 0 && num3 < length);
			goto IL_A0;
			Block_2:
			if (num - pos < num6 && !tabEnd)
			{
				num2 += num6 - (num - pos);
			}
			IL_A0:
			return pos - num2;
		}
		private void UpdateDelimTable()
		{
			this.delimTable.Clear();
			char[] array = this.delimiters;
			for (int i = 0; i < array.Length; i++)
			{
				char c = array[i];
				this.delimTable[c] = c;
			}
		}
		protected bool IsDelimiter(Hashtable delims, string s, int pos)
		{
			char c = s[pos];
			return c <= ' ' || this.delimTable.ContainsKey(c) || (delims != null && delims.Contains(c));
		}
		protected virtual void OnDelimitersChanged()
		{
			this.UpdateDelimTable();
		}
		public virtual bool IsDelimiter(string s, int pos)
		{
			char c = s[pos];
			return c <= ' ' || this.delimTable.ContainsKey(c);
		}
		public virtual bool IsDelimiter(int index, int pos)
		{
			return this.IsDelimiter(this[index], pos);
		}
		public virtual bool IsDelimiter(char ch)
		{
			return ch <= ' ' || this.delimTable.ContainsKey(ch);
		}
		public virtual bool IsWhitespace(string s, int pos)
		{
			return TextStrings.IsWhitespace(s[pos]);
		}
		public virtual bool GetWord(string s, int pos, out int left, out int right)
		{
			return this.GetWord(s, pos, out left, out right, null);
		}
		public virtual bool GetWord(string s, int pos, out int left, out int right, Hashtable delims)
		{
			int length = s.Length;
			left = 0;
			right = 0;
			bool result;
			if (s != string.Empty && pos <= length)
			{
				if (pos == length)
				{
					pos--;
				}
				if (this.IsWhitespace(s, pos))
				{
					left = pos;
					while (left > 0 && this.IsWhitespace(s, left - 1))
					{
						left--;
					}
					right = pos;
					while (right < length - 1 && this.IsWhitespace(s, right + 1))
					{
						right++;
					}
				}
				else
				{
					if (this.IsDelimiter(delims, s, pos))
					{
						left = pos;
						while (left > 0 && this.IsDelimiter(delims, s, left - 1) && !this.IsWhitespace(s, left - 1))
						{
							left--;
						}
						right = pos;
						while (right < length - 1 && this.IsDelimiter(delims, s, right + 1) && !this.IsWhitespace(s, right + 1))
						{
							right++;
						}
					}
					else
					{
						left = pos;
						while (left > 0 && !this.IsDelimiter(delims, s, left - 1))
						{
							left--;
						}
						right = pos;
						while (right < length - 1 && !this.IsDelimiter(delims, s, right + 1))
						{
							right++;
						}
					}
				}
				result = true;
			}
			else
			{
				result = false;
			}
			return result;
		}
		public virtual bool GetWord(int index, int pos, out int left, out int right)
		{
			return this.GetWord(this[index], pos, out left, out right);
		}
		public virtual string GetTextAt(int pos, int line)
		{
			string text = this[line];
			int num;
			int num2;
			string result;
			if (this.GetWord(text, pos, out num, out num2))
			{
				result = text.Substring(num, num2 - num + 1);
			}
			else
			{
				result = string.Empty;
			}
			return result;
		}
		public virtual string GetTextAt(Point position)
		{
			return this.GetTextAt(position.X, position.Y);
		}
	
		protected virtual void OnOwnerChanged()
		{
		}
		public virtual int BeginUpdate()
		{
			if (this.updateCount == 0)
			{
				this.firstChanged = -1;
				this.lastChanged = -1;
			}
			this.updateCount++;
			return this.updateCount;
		}
		public virtual int EndUpdate()
		{
			this.updateCount--;
			if (this.updateCount == 0)
			{
				this.Update();
			}
			return this.updateCount;
		}
	
		public virtual void AddNotifier(INotifier sender)
		{
			this.notifyHandler = (EventHandler)Delegate.Combine(this.notifyHandler, new EventHandler(sender.Notification));
		}
		public virtual void RemoveNotifier(INotifier sender)
		{
			this.notifyHandler = (EventHandler)Delegate.Remove(this.notifyHandler, new EventHandler(sender.Notification));
		}
		public virtual void Update()
		{
			if (this.updateCount == 0)
			{
				this.Notify(EventArgs.Empty);
			}
		}
		public virtual void Notify(EventArgs e)
		{
			if (this.notifyHandler != null)
			{
				this.notifyHandler(this, e);
			}
			this.firstChanged = -1;
			this.lastChanged = -1;
		}
	}
}
